package com.zuul.simple.filter.pre;

import com.zuul.simple.filter.MyZuulFilter;
import com.zuul.simple.http.RequestContext;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.RequestEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;

/**
 * @author : kebukeyi
 * @date :  2021-05-21 11:53
 * @description :
 * 这个是PreFilter,前置执行过滤器，负责封装请求。
 * 步骤如下所示
 * (1)封装请求头
 * (2)封装请求体
 * (3)构造出RestTemplate能识别的RequestEntity
 * (4)将RequestEntity放入全局threadlocal之中
 * @question :
 * @usinglink :
 **/
public class RequestWrapperFilter extends MyZuulFilter {
    @Override
    public String filterType() {
        // TODO Auto-generated method stub
        return "pre";
    }

    @Override
    public int filterOrder() {
        // TODO Auto-generated method stub
        return -1;
    }

    @Override
    public void run() {
        String rootURL = "http://localhost:9090";
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest servletRequest = ctx.getRequest();
        String targetURL = rootURL + servletRequest.getRequestURI();
        RequestEntity requestEntity = null;
        try {
            requestEntity = createRequestEntity(servletRequest, targetURL);
        } catch (IOException | URISyntaxException e) {
            e.printStackTrace();
        }
        //4、将requestEntity放入全局threadlocal之中
        ctx.setRequestEntity(requestEntity);
    }

    private RequestEntity createRequestEntity(HttpServletRequest request, String rootURL) throws IOException, URISyntaxException {
        String method = request.getMethod();
        HttpMethod httpMethod = HttpMethod.resolve(method);
        //1、封装请求头
        MultiValueMap headers = createRequestHeaders(request);
        //2、封装请求体
        byte[] body = createRequestBody(request);
        //3、构造出RestTemplate能识别的RequestEntity
        RequestEntity requestEntity = new RequestEntity(body, headers, httpMethod, new URI(rootURL));
        return requestEntity;
    }

    private byte[] createRequestBody(HttpServletRequest request) throws IOException {
        InputStream inputStream = request.getInputStream();
        return StreamUtils.copyToByteArray(inputStream);
    }

    private MultiValueMap createRequestHeaders(HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        List headerNames = Collections.list(request.getHeaderNames());
        for (Object headerName : headerNames) {
            List headerValues = Collections.list(request.getHeaders((String) headerName));
            for (Object headerValue : headerValues) {
                headers.add((String) headerName, (String) headerValue);
            }
        }
        return headers;
    }


}
 
